package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.heima.article.client.ArticleFeign;
import com.heima.common.aliyun.GreenImageUrlScan;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.common.delayTask.RedisDelayedQueueUtil;
import com.heima.common.enums.AppHttpCodeEnum;
import com.heima.common.exception.LeadException;
import com.heima.common.util.BeanHelper;
import com.heima.common.util.SensitiveWordUtil;
import com.heima.model.media.dtos.WmNewsResultDTO;
import com.heima.wemedia.entity.WmNews;
import com.heima.wemedia.entity.WmSensitive;
import com.heima.wemedia.service.WmNewsAuditService;
import com.heima.wemedia.service.WmNewsService;
import com.heima.wemedia.service.WmSensitiveService;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @Author RMY
 * @Date 2021/11/28 16:47
 * @Version 1.0
 */
@Slf4j
@Service
public class WmNewsAuditServiceImpl implements WmNewsAuditService {
    @Autowired
    private WmNewsService wmNewsService;
    @Autowired
    private ArticleFeign articleFeign;
    @Autowired
    private GreenImageUrlScan imageUrlScan;
    @Autowired
    private GreenTextScan textScan;
    @Autowired
    private RedisDelayedQueueUtil redisDelayedQueueUtil;
    @Override
    @Async
    public void auditWmNews(Integer wmNewsId) {
        //查询自媒体文章
        WmNews wmNews = wmNewsService.getById(wmNewsId);
        if (wmNews == null) {
            throw new LeadException(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
//        只处理待审核
        if (wmNews.getStatus().intValue()!=1) {
            log.info("当前自媒体文章不是 待审核状态");
            return;
        }
        //从内容中提取纯文本内容和图片
        Map<String, Object> map = handleTextAndImages(wmNews);
//        获取所有文本内容
        String text = map.get("content").toString();
//            获得所用图片地址
        Set<String> urls = (Set<String>) map.get("image");
        //检查是否有敏感词
        boolean b = handlerSensitiveScan(text, wmNewsId);
        if (!b){
            log.error("敏感词检测不通过");
            throw new LeadException(AppHttpCodeEnum.TEXT_ILLEGAL);
        }
        //审核文本内容  阿里云接口
        boolean isTextPass = handlerAliyunText(wmNewsId, text);
        if (!isTextPass) {
            log.info("阿里云文本检测不通过，wmNewsId={}", wmNewsId);
            return;
        }
        //审核图片  阿里云接口
        boolean isImagePass = handleImageScan(urls, wmNewsId);
        if (!isImagePass) {
            log.info("阿里云图片检测不通过,wmNewsId={}", wmNewsId);
            return;
        }
//          如果没到发布时间，修改审核状态为8 审核通过,待发布
        if(wmNews.getPublishTime() != null &&
                wmNews.getPublishTime().getTime()> System.currentTimeMillis()){
            //修改当前文章的状态
            updateWmNewsStatus(wmNewsId,8,null,null);
            Date publishTime = wmNews.getPublishTime();
            //没有到发布时间则放入延迟任务
            log.info("没有到发布时间，放入延迟任务，wmNewsId={},publishTime={}",wmNewsId,publishTime);
            //计算延迟时间
            long delay = publishTime.getTime() - System.currentTimeMillis();
            log.info("wmNewsId={},延迟时间delay={}",wmNewsId,delay);
            redisDelayedQueueUtil.addQueue(wmNewsId,delay, TimeUnit.MILLISECONDS,"wm.news.pub");
            return;
        }
        //审核成功，发布文章，保存app端的相关的文章数据
        pubWmNews(wmNews);
    }



    /**
     * 审核图片
     *
     * @param images
     * @param wmNewsId
     * @return
     */
    private boolean handleImageScan(Set<String> images, Integer wmNewsId) {
        if (CollectionUtils.isEmpty(images)) {
            return true;
        }
        //获得图片List
        List<String> imageList = new ArrayList<>();
        for (String image : images) {
            imageList.add(image);
        }
        if (CollectionUtils.isEmpty(imageList)) {
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR);
        }
        //审核图片
        try {
            Map<String, String> map = imageUrlScan.imageScan(imageList);
            if (CollectionUtils.isEmpty(map)) {
                log.error("图片接口返回的map为空");
                throw new LeadException(AppHttpCodeEnum.SERVER_ERROR);
            }
            String suggestion = map.get("suggestion");
            if (StringUtils.isBlank(suggestion)) {
                log.error("图片接口返回的suggestion为空");
                throw new LeadException(AppHttpCodeEnum.SERVER_ERROR);
            }
            if ("pass".equals(suggestion)) {
                log.info("阿里云图片审核通过");
                return true;
            } else if ("review".equals(suggestion)) {
                log.info("阿里云图片审核不确定，转人工审核");
//              修改状态 ，改成3
                updateWmNewsStatus(wmNewsId, 3, map.get("label"), null);
                return false;
            } else {
                log.info("阿里云图片审核不通过");
//              修改状态，改成2
                updateWmNewsStatus(wmNewsId, 2, map.get("label"), null);
                return false;
            }
        } catch (Exception e) {
            log.error("调用阿里云图片接口失败！");
            e.printStackTrace();
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR);
        }
    }

    /**
     * 阿里云文本接口审核文本
     *
     * @param text
     * @return
     */
    private boolean handlerAliyunText(Integer wmNewsId, String text) {

        try {
            Map<String, String> map = textScan.greenTextScan(text);
            if (CollectionUtils.isEmpty(map)) {
                log.error("文本接口返回的map为空");
                throw new LeadException(AppHttpCodeEnum.SERVER_ERROR);
            }
            String suggestion = map.get("suggestion");
            if (StringUtils.isBlank(suggestion)) {
                log.error("文本接口返回的suggestion为空");
                throw new LeadException(AppHttpCodeEnum.SERVER_ERROR);
            }
            if ("pass".equals(suggestion)) {
                log.info("阿里云文本审核通过");
                return true;
            } else if ("review".equals(suggestion)) {
                log.info("阿里云文本审核不确定，转人工审核");
//              修改状态 ，改成3
                updateWmNewsStatus(wmNewsId, 3, map.get("reason"), null);
                return false;
            } else {
                log.info("阿里云文本审核不通过");
//              修改状态，改成2
                updateWmNewsStatus(wmNewsId, 2, map.get("reason"), null);
                return false;
            }
        } catch (Exception e) {
            log.error("调用阿里云文本接口失败！");
            e.printStackTrace();
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR);
        }
    }

    /**
     * 修改自媒体文章状态
     *
     * @param wmNewsId
     * @param status
     * @param reason
     */
    private void updateWmNewsStatus(Integer wmNewsId, Integer status, String reason, Long articleId) {

        WmNews wmNews = new WmNews();
        wmNews.setId(wmNewsId);
        wmNews.setStatus(status);
        if (StringUtils.isNotBlank(reason)) {
            wmNews.setReason(reason);
        }
        if (articleId != null) {
            wmNews.setArticleId(articleId);
        }
        wmNewsService.updateById(wmNews);
    }
    /**
     * 1。从自媒体文章的内容中提取文本和图片
     * 2.提取文章的封面图片
     *
     * @param wmNews
     * @return
     */
    private Map<String, Object> handleTextAndImages(WmNews wmNews) {

        //存储纯文本内容
        StringBuilder stringBuilder = new StringBuilder();

        Set<String> images = new HashSet<>();

        //1。从自媒体文章的内容中提取文本和图片
        if (StringUtils.isNotBlank(wmNews.getContent())) {
            List<Map> maps = JSONArray.parseArray(wmNews.getContent(), Map.class);
            for (Map map : maps) {
                if (map.get("type").equals("text")) {
                    stringBuilder.append(map.get("value"));
                }

                if (map.get("type").equals("image")) {
                    images.add((String) map.get("value"));
                }
            }
        }
        //2.提取文章的封面图片
        if (StringUtils.isNotBlank(wmNews.getImages())) {
            String[] split = wmNews.getImages().split(",");
            images.addAll(Arrays.asList(split));
        }

        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("content", stringBuilder.toString());
        resultMap.put("images", images);
        return resultMap;
    }


    /**
     * 远程调用feign保存article
     * @param wmNews
     */
    @GlobalTransactional
    public void pubWmNews(WmNews wmNews) {
        WmNewsResultDTO wmNewsResultDTO = BeanHelper.copyProperties(wmNews, WmNewsResultDTO.class);
        //远程调用
        try {
            Long articleId = articleFeign.saveArticle(wmNewsResultDTO);
            updateWmNewsStatus(wmNews.getId(),9,null,articleId);
        } catch (Exception e) {
            log.error("远程调用article服务创建文章失败！");
            e.printStackTrace();
            throw new LeadException(AppHttpCodeEnum.SERVER_ERROR);
        }
    }
    @Autowired
    private WmSensitiveService wmSensitiveService;
    /**
     * 敏感词检索
     * @param text
     * @param wmUserId
     * @return
     */
    private boolean handlerSensitiveScan(String text,Integer wmUserId){
        //1.查询所有敏感词，进行对比
        List<WmSensitive> list = wmSensitiveService.list();
        //封装敏感词
        List<String> sensitiveWords = list.stream().map(WmSensitive::getSensitives).collect(Collectors.toList());
        //对比敏感词
        Map<String,Integer> map = SensitiveWordUtil.matchWords(sensitiveWords,text);
        if (!CollectionUtils.isEmpty(map)){
            log.info("包含敏感词"+map);
            String reason = "";
            //打印敏感词
            Set<String> set = map.keySet();
            for (String key : set) {
                if (reason.length()>0){
                    reason = reason+",";
                }
                reason = reason+key;
            }
            //修改文章状态
            updateWmNewsStatus(wmUserId,2,reason,null);
            return false;
        }
        return true;
    }
}
